const { ethers } = require('ethers');
require('dotenv').config();

/**
 * IPFS Hash 更新脚本
 * 用于更新新的IPFS hash并重新配置baseURI
 */

// 配置信息 - 请更新为你的新hash
const CONFIG = {
    // 新的IPFS文件夹hash - 请替换为你的实际hash
    newIPFSHash: "YOUR_NEW_IPFS_HASH_HERE",

    // 网络配置
    rpcUrl: process.env.SEPOLIA_RPC_URL,
    privateKey: process.env.PRIVATE_KEY,

    // 合约地址
    contractAddress: "YOUR_CONTRACT_ADDRESS_HERE"
};

// 合约ABI
const CONTRACT_ABI = [
    "function setBaseURI(string memory newBaseURI) public",
    "function baseURI() public view returns (string)",
    "function mintNFT(address to, string memory _tokenURI) public payable returns (uint256)",
    "function tokenURI(uint256 tokenId) public view returns (string)",
    "function totalSupply() public view returns (uint256)"
];

class IPFSHashUpdater {
    constructor() {
        this.provider = null;
        this.wallet = null;
        this.contract = null;
    }

    async initialize() {
        console.log("🚀 初始化IPFS Hash更新器...");

        // 检查配置
        if (CONFIG.newIPFSHash === "YOUR_NEW_IPFS_HASH_HERE") {
            throw new Error("请先设置新的IPFS hash！");
        }

        if (CONFIG.contractAddress === "YOUR_CONTRACT_ADDRESS_HERE") {
            throw new Error("请先设置合约地址！");
        }

        // 初始化provider和wallet
        this.provider = new ethers.providers.JsonRpcProvider(CONFIG.rpcUrl);
        this.wallet = new ethers.Wallet(CONFIG.privateKey, this.provider);

        // 初始化合约
        this.contract = new ethers.Contract(
            CONFIG.contractAddress,
            CONTRACT_ABI,
            this.wallet
        );

        console.log("✅ 初始化完成");
        console.log(`📝 钱包地址: ${this.wallet.address}`);
        console.log(`🔗 合约地址: ${CONFIG.contractAddress}`);
        console.log(`🆔 新IPFS Hash: ${CONFIG.newIPFSHash}`);
    }

    /**
     * 更新baseURI
     */
    async updateBaseURI() {
        console.log("\n🔧 更新BaseURI...");

        const newBaseURI = `ipfs://${CONFIG.newIPFSHash}/`;
        console.log(`📤 新baseURI: ${newBaseURI}`);

        try {
            // 查看当前baseURI
            const currentBaseURI = await this.contract.baseURI();
            console.log(`📋 当前baseURI: ${currentBaseURI}`);

            // 更新baseURI
            const tx = await this.contract.setBaseURI(newBaseURI);
            console.log(`⏳ 交易哈希: ${tx.hash}`);
            await tx.wait();
            console.log("✅ baseURI更新成功");

            // 验证更新
            const updatedBaseURI = await this.contract.baseURI();
            console.log(`📋 更新后baseURI: ${updatedBaseURI}`);

            return updatedBaseURI;
        } catch (error) {
            console.error("❌ 更新baseURI失败:", error.message);
            throw error;
        }
    }

    /**
     * 测试新hash的访问
     */
    async testNewHashAccess() {
        console.log("\n🌐 测试新IPFS Hash访问...");

        const testFiles = [
            "metadata/1.json",
            "metadata/2.json",
            "metadata/3.json",
            "myNFT1.jpeg",
            "myNFT2.jpeg"
        ];

        console.log(`📁 测试文件列表:`);
        for (const file of testFiles) {
            const ipfsURI = `ipfs://${CONFIG.newIPFSHash}/${file}`;
            const httpURI = `https://ipfs.io/ipfs/${CONFIG.newIPFSHash}/${file}`;

            console.log(`\n📄 ${file}:`);
            console.log(`   IPFS URI: ${ipfsURI}`);
            console.log(`   HTTP访问: ${httpURI}`);
            console.log(`   💡 你可以在浏览器中访问HTTP链接来测试`);
        }
    }

    /**
     * 铸造测试NFT
     */
    async mintTestNFT(recipient) {
        console.log("\n🎨 铸造测试NFT...");

        try {
            const metadataFile = "metadata/1.json";
            console.log(`📤 铸造metadata: ${metadataFile}`);

            const tx = await this.contract.mintNFT(
                recipient,
                metadataFile,
                { value: ethers.utils.parseEther("0") }
            );

            console.log(`⏳ 交易哈希: ${tx.hash}`);
            await tx.wait();
            console.log("✅ 测试NFT铸造成功");

            // 查询结果
            const totalSupply = await this.contract.totalSupply();
            const tokenId = totalSupply.toNumber();
            const tokenURI = await this.contract.tokenURI(tokenId);

            console.log(`🆔 Token ID: ${tokenId}`);
            console.log(`🔗 最终URI: ${tokenURI}`);

            // 验证URI
            const expectedURI = `ipfs://${CONFIG.newIPFSHash}/${metadataFile}`;
            if (tokenURI === expectedURI) {
                console.log("✅ URI验证成功！");
            } else {
                console.log("❌ URI验证失败！");
                console.log(`预期: ${expectedURI}`);
                console.log(`实际: ${tokenURI}`);
            }

            return { tokenId, tokenURI };
        } catch (error) {
            console.error("❌ 测试NFT铸造失败:", error.message);
            throw error;
        }
    }

    /**
     * 运行完整的更新流程
     */
    async runUpdateProcess(recipient) {
        console.log("🎯 开始IPFS Hash更新流程...");
        console.log("=" * 50);

        try {
            await this.initialize();

            // 1. 更新baseURI
            await this.updateBaseURI();

            // 2. 测试新hash访问
            await this.testNewHashAccess();

            // 3. 铸造测试NFT
            const testResult = await this.mintTestNFT(recipient);

            // 4. 总结
            console.log("\n📊 更新结果总结:");
            console.log("=" * 30);
            console.log(`✅ 新IPFS Hash: ${CONFIG.newIPFSHash}`);
            console.log(`✅ BaseURI已更新`);
            console.log(`✅ 测试NFT铸造成功 (Token ID: ${testResult.tokenId})`);
            console.log(`✅ URI验证通过`);

            console.log("\n🎉 IPFS Hash更新完成！");
            console.log("💡 你现在可以使用新的hash来铸造NFT了");

            return testResult;

        } catch (error) {
            console.error("❌ 更新流程失败:", error.message);
            throw error;
        }
    }
}

// 使用示例
async function main() {
    const updater = new IPFSHashUpdater();

    // 设置接收者地址
    const recipient = "YOUR_WALLET_ADDRESS"; // 请替换为实际地址

    if (recipient === "YOUR_WALLET_ADDRESS") {
        console.error("❌ 请先设置正确的接收者地址！");
        return;
    }

    try {
        await updater.runUpdateProcess(recipient);
    } catch (error) {
        console.error("❌ 执行失败:", error.message);
    }
}

// 如果直接运行此脚本
if (require.main === module) {
    main().catch(console.error);
}

module.exports = { IPFSHashUpdater, CONFIG };
